package test29.Lambda;

import org.junit.Test;

import java.io.PrintStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.function.*;

/**
 * 一、方法引用使用场景：若 Lambda 体中的功能，已经有方法提供了实现，可以使用方法引用
 * （可以将方法引用理解为 Lambda 表达式的另外一种表现形式）
 * 2.方法引用，本质上就是lambda表达式，而lambda表达式作为函数式接口的实例，所以方法引用，也是函数式接口的实例
 *
 * 3.使用格式： 类（或对象）::
 * 4.具体分为如下三种情况
 * 对象的引用 :: 实例方法名（非静态方法）
 * 类名 :: 静态方法名
 * 类名 :: 实例方法名
 * <p>
 * 5.方法引用使用要求：要求接口中的抽象方法的形参列表和返回值类型和方法引用的方法的形参列表和返回值类型相同
 */
public class MethodRefTest {
    //情况一： 对象::实例方法
    //consumer中的void accept（T t）
    //PrintStream中的void println（T t）
    @Test
    public void test1() {
        Consumer<String> con1 = s -> System.out.println(s);
        con1.accept("北京");

        System.out.println("================");
        PrintStream ps = System.out;
        Consumer<String> con2 = ps::println;
        con2.accept("beijing");
    }

    //Supplier中的T get()
    //Employee中的String getName()
    @Test
    public void test2() {
        Employee employee = new Employee(1001, "Tom", 23, 5600);
        Supplier<String> sup1 = () -> employee.getName();
        System.out.println(sup1.get());

        System.out.println("==============");
        Supplier<String> sup2 = employee::getName;
        System.out.println(sup2.get());
    }

    //情况二：类名 :: 静态方法名
    //Comparator中的int compare(T t1,T t2)
    //Integer中的int compare（T t1,T t2）
    @Test
    public void test3() {
        Comparator<Integer> com1 = (t1, t2) -> Integer.compare(t1, t2);
        System.out.println(com1.compare(12, 21));

        System.out.println("================");
        Comparator<Integer> com2 = Integer::compare;
        System.out.println(com2.compare(12, 3));
    }

    //Function中的 R apply（T t）
    //Math 中的 Long round(Double d)
    @Test
    public void test4() {
        //接受 Double 类型参数并返回 Long 类型结果的函数。
        Function<Double, Long> func1 = d -> Math.round(d);
        System.out.println("=============");
        Function<Double, Long> func2 = Math::round;

    }

    //情况三：类名 :: 实例方法名
    //Comparator中的int compare(T t1,T t2)
    //String 中在int t1.compareTo(t2)
    @Test
    public void test5(){
        Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
        System.out.println(com1.compare("abc","abd"));
        System.out.println("====================");
        Comparator<String> com2 = String ::compareTo;
        System.out.println(com2.compare("abc","abd"));
    }
    //BiPredicate中的boolean test(T t1,T t2);
    //String中的boolean t1.equals(t2)
    @Test
    public void test6(){
        BiPredicate<String,String> pre1 = (s1,s2) -> s1.equals(s2);
        System.out.println(pre1.test("abc","abd"));

        System.out.println("==============");
        BiPredicate<String,String> pre2 = String :: equals;
    }

    //Function中的R apply(T t)
    //Employee中的String getName();
    @Test
    public void test7(){
        new Employee(1001,"Jerry",23,6000);
        Function<Employee,String> func1 = e -> e.getName();
        System.out.println("==============");
        Function<Employee,String> func2 = Employee::getName;
    }

    //构造器引用 和方法引用类是，函数式接口的抽象方法的形参列表和构造器的形参列表一致
    //抽象方法的返回值类型即为构造器所属的类的类型
    //Supplier中的T get()
    //Employee的空参构造器：Employee()
    @Test
    public void test8(){
        Supplier<Employee> sup = new Supplier<Employee>() {
            @Override
            public Employee get() {
                return new Employee();
            }
        };
        System.out.println("=============");
        Supplier<Employee> sup2 = () -> new Employee();

        System.out.println("===============");
        Supplier<Employee> sup3 = Employee :: new;
    }
    //Function中的R apply（T t）
    @Test
    public void test9(){
        Function<Integer,Employee> func1 = id -> new Employee(id);
        Employee apply = func1.apply(1001);

        System.out.println("===========");
        Function<Integer,Employee> func2 = Employee::new;
        Employee apply1 = func2.apply(1002);
        System.out.println(apply1);
    }

    //BiFunction中的R apply（T t，U u）
    @Test
    public void test10(){
        BiFunction<String,Integer,Employee> func1 = (name,id) -> new Employee(name,id);
        System.out.println(func1.apply("Tom",1001));
        System.out.println("==============");
        BiFunction<String,Integer ,Employee> func2 = Employee :: new;
        System.out.println(func2.apply("Tom",1001 ));
    }

    //数组引用
    //Function 中 R apply(T t)
    @Test
    public void test11(){
        Function<Integer,String[]> func1 = length -> new String[length];
        String[] apply = func1.apply(5);
        System.out.println(Arrays.toString(apply));

        System.out.println("============");
        Function<Integer,String[]> function = String[] :: new;
        String[] apply1 = function.apply(10);
        System.out.println(Arrays.toString(apply1));
    }
}
